home *** CD-ROM | disk | FTP | other *** search
- #include <Windows.h>
-
- /*----------------------------------------------------------------------*/
-
- #define HELP_WIND_W 450
- #define HELP_MENU_H 20
- #define HELP_LINE_H 13
- #define HELP_LINES 21
- #define HELP_TOP_SPACE 5
- #define HELP_BOT_SPACE 1
- #define HELP_DESCENT 4
- #define HELP_LEFT_SPACE 5
-
- #define HELP_INDEX_START 2
-
- #define HELP_SCROLL_MAX (2*(HELP_LINES*HELP_LINE_H+HELP_TOP_SPACE+HELP_BOT_SPACE-15-15-16))
-
- #define HELP_MENUS_MAX 20
- #define HELP_ITEMS_MAX 400
- #define HELP_MENUS_ID 200
-
- #define HELP_CACHE_LENGTH 3000
- #define HELP_CACHE_BEFORE 1500
- #define HELP_NEWLINE 13
-
- int help_error = 1; /* error flag */
- static int help_refnum; /* refnum of help file */
- static long help_length; /* length of help file */
- static long help_prefix; /* length of prefix */
-
- static char help_buffer[HELP_CACHE_LENGTH+2]; /* has newline at both ends */
- static char *help_cache, *help_cache_end; /* limits of cache block */
- static char *help_line, *help_line_end; /* limits of current line */
- static long help_cache_pos; /* pos of cache in file */
-
- #define help_pos(ptr) (help_cache_pos+((ptr)-help_cache))
-
- static MenuHandle help_menus[HELP_MENUS_MAX]; /* help window menus */
- static Handle help_menu_bar; /* help window's menu bar */
- static int help_nb_menus; /* nb of menus in help window */
- static int help_nb_items; /* total nb of items in menus */
- static int help_menus_items[HELP_MENUS_MAX]; /* offset into help_items_val */
- static long help_items_val[HELP_ITEMS_MAX]; /* index into document body */
- static Rect help_menus_rects[HELP_MENUS_MAX]; /* selection area for each menu */
-
- static WindowPtr help_wind = NULL; /* the help window */
- static ControlHandle help_ctl; /* its vertical scroll bar */
-
- static long help_current_page; /* position of current page in doc body */
-
- static int help_current_menu; /* temporary */
-
- /*----------------------------------------------------------------------*/
-
- static void help_error_set()
- {
- ioParam pb;
-
- pb.ioRefNum = help_refnum;
- PBClose( &pb, 0 );
-
- help_error = 1;
- }
-
- static void help_open_file( filename )
- Str255 filename;
- {
- ioParam pb;
-
- help_length = 0;
-
- pb.ioNamePtr = filename;
- pb.ioVRefNum = 0;
- pb.ioVersNum = 0;
- pb.ioPermssn = fsRdPerm;
- pb.ioMisc = 0;
- PBOpen( &pb, 0 );
-
- if (pb.ioResult != noErr) { help_error = 1; return; }
-
- help_refnum = pb.ioRefNum;
-
- PBGetEOF( &pb, 0 );
-
- if (pb.ioResult != noErr) { help_error_set(); return; }
-
- help_length = (long)pb.ioMisc;
- }
-
- static void help_read_block( pos, count, buf, len )
- long pos, count;
- char *buf;
- long *len;
- {
- ioParam pb;
-
- *len = 0;
-
- pb.ioRefNum = help_refnum;
- pb.ioPosMode = 1; /* relative to start */
- pb.ioPosOffset = pos;
- PBSetFPos( &pb, 0 );
-
- if (pb.ioResult != noErr)
- {
- if (pb.ioResult != eofErr) help_error_set();
- return;
- }
-
- pb.ioRefNum = help_refnum;
- pb.ioBuffer = buf;
- pb.ioReqCount = count;
- pb.ioPosMode = 1; /* relative to start */
- PBRead( &pb, 0 );
-
- if ((pb.ioResult != noErr) && (pb.ioResult != eofErr))
- { help_error_set(); return; }
-
- *len = pb.ioActCount;
- }
-
- static void help_load_cache( pos )
- long pos;
- {
- long len;
- if (pos < 0) pos = 0;
- help_cache_pos = pos;
- len = help_length-pos;
- if (len < 0) len = 0;
- else if (len > HELP_CACHE_LENGTH) len = HELP_CACHE_LENGTH;
- if (len > 0) help_read_block( pos, len, help_cache, &len );
- while (len < HELP_CACHE_LENGTH) help_cache[len++] = HELP_NEWLINE;
- help_cache_end = help_cache+len;
- help_cache[-1] = HELP_NEWLINE;
- help_cache_end[0] = HELP_NEWLINE;
- }
-
- static void help_load_line( pos )
- long pos;
- {
- register char *p, *q;
- p = help_cache+(pos-help_cache_pos);
- if ((p > help_cache) && (p < help_cache_end))
- {
- q = p;
- while (*--p != HELP_NEWLINE) ;
- while (*q++ != HELP_NEWLINE) ;
- help_line = p+1;
- help_line_end = q-1;
- if ((help_line > help_cache) && (help_line_end < help_cache_end)) return;
- }
-
- help_load_cache( pos-HELP_CACHE_BEFORE );
- p = help_cache+(pos-help_cache_pos);
- if (p < help_cache) p = help_cache;
- else if (p > help_cache_end) p = help_cache_end;
- q = p;
- while (*--p != HELP_NEWLINE) ;
- while (*q++ != HELP_NEWLINE) ;
- help_line = p+1;
- help_line_end = q-1;
- }
-
- /*----------------------------------------------------------------------*/
-
- static void help_menus_rects_init()
- {
- Rect r = { 0, 0, HELP_MENU_H, 0 };
- short *p = *(short **)help_menu_bar;
- register short i = 0;
- short n = *p++; /* #menus * 6 */
- short x = *p++; /* r.right of last menu title */
-
- p += 3; /* skip unused x & handle */
- r.left = *p-5;
- n -= 6;
- do
- {
- p += 3; /* skip unused x & handle */
- r.right = *p-5;
- help_menus_rects[i++] = r;
- r.left = r.right;
- n -= 6;
- } while(n > 0);
- r.right = x-5;
- help_menus_rects[i] = r;
- }
-
- static void help_menus_init()
- {
- unsigned char buffer[100];
- int nb_items;
- int style;
- long value;
- register char *p;
- register int i;
-
- help_nb_menus = 0;
- help_nb_items = 0;
-
- help_cache = help_buffer+1;
-
- help_load_cache( 0 );
- help_load_line( 0 );
- p = help_line;
-
- if (help_error) goto err;
-
- while (*p != HELP_NEWLINE)
- {
- i = 0;
- while (p < help_line_end) { buffer[i+1] = *p++; i++; }
- buffer[0] = i;
- help_menus[help_nb_menus] = NewMenu( HELP_MENUS_ID+help_nb_menus, buffer );
- help_menus_items[help_nb_menus] = help_nb_items;
-
- help_load_line( help_pos(help_line_end+1) );
- p = help_line;
- if (help_error) goto err;
-
- nb_items = 0;
- while (*p != HELP_NEWLINE)
- {
- i = 0;
- while ((unsigned char)*p >= 32) { buffer[i+1] = *p++; i++; }
- buffer[0] = i;
- p++;
- style = 0;
- if (*p == 'i') { style += 2; p++; }
- if (*p == 'b') { style += 1; p++; }
- value = 0;
- while (*p != HELP_NEWLINE) value = value*10 + ((*p++)-'0');
- help_items_val[help_nb_items++] = value;
- nb_items++;
- AppendMenu( help_menus[help_nb_menus], "\p " );
- SetItem( help_menus[help_nb_menus], nb_items, buffer );
- SetItemStyle( help_menus[help_nb_menus], nb_items, style );
-
- help_load_line( help_pos(help_line_end+1) );
- p = help_line;
- if (help_error) goto err;
- }
-
- help_nb_menus++;
-
- help_load_line( help_pos(help_line_end+1) );
- p = help_line;
- if (help_error) goto err;
- }
-
- help_menus_items[help_nb_menus] = help_nb_items;
-
- if (help_nb_menus == 0) help_error_set();
-
- err:
-
- help_prefix = help_pos(help_line_end+1);
-
- ClearMenuBar();
- for (i=0; i<help_nb_menus; i++) InsertMenu( help_menus[i], 0 );
- help_menu_bar = GetMenuBar();
-
- help_menus_rects_init();
- }
-
- static void help_draw_menu_bar()
- {
- int i;
- TextFont( 0 );
- TextFace( 0 );
- TextSize( 12 );
- for (i=0; i<help_nb_menus; i++)
- {
- MoveTo( help_menus_rects[i].left + 9, help_menus_rects[i].bottom - 5 );
- HLock( help_menus[i] );
- DrawString( (*help_menus[i])->menuData );
- HUnlock( help_menus[i] );
- }
- MoveTo( 0, HELP_MENU_H-1 );
- LineTo( HELP_WIND_W, HELP_MENU_H-1 );
- }
-
- static pascal void help_menu_hook()
- {
- Point p;
- WindowPtr wind = FrontWindow();
- long sysA5 = SetA5( GetWRefCon( wind ) );
- GrafPtr save_port;
- GetPort( &save_port );
- SetPort( wind );
- GetMouse( &p );
- if ((p.v < HELP_MENU_H) &&
- !PtInRect( p, &help_menus_rects[help_current_menu] ))
- PostEvent( mouseUp, 0L );
- SetPort( save_port );
- SetA5( sysA5 );
- }
-
- static long help_menu_select( event )
- EventRecord *event;
- {
- int i;
- ProcPtr save_menu_hook;
- Point p;
- long selection = 0;
- SetWRefCon( help_wind, SetCurrentA5() ); /* save A5 in window's refCon */
- save_menu_hook = MenuHook;
- MenuHook = (ProcPtr)help_menu_hook;
- while( Button() ) /* don't use StillDown() here !? */
- {
- GetMouse( &p );
- for (i=0; i<help_nb_menus; i++)
- {
- help_current_menu = i;
- if (PtInRect( p, &help_menus_rects[i] ))
- {
- Rect r = help_menus_rects[i];
- InsetRect( &r, 0, 1 );
- r.right += 5;
- InvertRect( &r );
- p.h = r.left + 1;
- p.v = r.bottom + 1;
- LocalToGlobal( &p );
- InsertMenu( help_menus[i], -1 );
- CalcMenuSize( help_menus[i] ); /* Work around Menu Mgr bug */
- selection = PopUpMenuSelect( help_menus[i], p.v, p.h, 0 );
- DeleteMenu( HELP_MENUS_ID + i );
- InvertRect( &r );
- break;
- }
- }
- }
- MenuHook = save_menu_hook;
- return selection;
- }
-
- static void help_current_page_set( pos )
- long pos;
- {
- if (pos < 0) pos = 0;
- else if (pos > (help_length-help_prefix)) pos = (help_length-help_prefix);
- help_current_page = pos;
- }
-
- void help_begin( title, filename )
- Str255 title, filename;
- {
- Rect r;
-
- help_error = 0;
-
- r.top = 40;
- r.left = 28;
- r.bottom = r.top + (HELP_MENU_H+HELP_TOP_SPACE+HELP_LINES*HELP_LINE_H+HELP_BOT_SPACE);
- r.right = r.left + HELP_WIND_W;
-
- help_wind = NewWindow( 0L, &r, title, 0, 4, (WindowPtr)-1L, 1, 0L );
- if (help_wind == NULL) { help_error = 1; return; }
- SetPort( help_wind );
- TextFont( 0 );
- TextFace( 0 );
- TextSize( 12 );
-
- r.top = HELP_MENU_H-1;
- r.left = HELP_WIND_W-15;
- r.bottom = (HELP_MENU_H+HELP_TOP_SPACE+HELP_LINES*HELP_LINE_H+HELP_BOT_SPACE)+1;
- r.right = HELP_WIND_W+1;
-
- help_ctl = NewControl( help_wind, &r, "\p", 1, 0, 0, (int)HELP_SCROLL_MAX, scrollBarProc, 0 );
- if (help_ctl == NULL) { help_wind = NULL; help_error = 1; return; }
-
- help_open_file( filename );
-
- if (!help_error) help_menus_init();
-
- if (help_error) help_wind = NULL;
-
- help_current_page_set( 0 );
- }
-
- void help_end()
- {
- if (help_wind != NULL)
- {
- DisposeWindow( help_wind );
- help_error_set();
- }
- }
-
- /*----------------------------------------------------------------------*/
-
- /* Display of the document's text */
-
- static int help_offsv( f )
- int f;
- {
- switch (f%3)
- {
- case 0: switch (f/9)
- { case 0: return 0; case 1: return 1; case 2: return 0; }
- case 1: return 2;
- case 2: return -2;
- }
- }
-
- static int help_offsh(f)
- int f;
- { if (f/3%3 == 2) return -1; else return 0; }
-
- static void help_select_font( f, oldf )
- int f, oldf;
- {
- switch (f/9)
- {
- case 0: TextFont(1); TextSize(9); break; /* Geneva, 9 pt */
- case 1: TextFont(1); TextSize(12); break; /* Geneva, 12 pt */
- case 2: TextFont(4); TextSize(9); break; /* Monaco, 9 pt */
- }
- switch (f/3%3)
- {
- case 0: TextFace(0); break; /* plain */
- case 1: switch (f/9)
- {
- case 0: TextFace(1); break; /* bold */
- case 1: TextFace(5); break; /* bold underline */
- case 2: TextFace(33); break; /* bold condensed */
- }
- break;
- case 2: TextFace(2); break; /* italic */
- }
- Move( help_offsh(f)-help_offsh(oldf), help_offsv(f)-help_offsv(oldf) );
- }
-
- /* drawing of currently cached line */
-
- static void help_draw_line()
- {
- register char *p;
- int f;
-
- help_select_font( 0, 0 );
- f = 0;
-
- p = help_line;
- while (p < help_line_end)
- {
- register unsigned char c = *p;
- char *last = p;
- while ((c >= 32) && (c <= 227)) { p++; c = *p; }
- if (last < p) DrawText( last, 0, p-last );
- p++;
- if (c == 13)
- goto line_end;
- else if (c < 32)
- Move( c, 0 );
- else if (c > 227)
- {
- help_select_font( 255-c, f );
- f = 255-c;
- }
- }
- line_end: ;
- }
-
- /* drawing of current page from lines 'lo' to 'hi-1' */
-
- static void help_draw_lines( lo, hi )
- int lo, hi;
- {
- long pos = help_current_page+help_prefix;
- int i;
-
- for (i=0; i<hi; i++)
- {
- help_load_line( pos );
- if (help_error) return;
- if (i >= lo)
- {
- MoveTo( HELP_LEFT_SPACE, HELP_MENU_H+HELP_TOP_SPACE+i*HELP_LINE_H+HELP_LINE_H-HELP_DESCENT );
- help_draw_line();
- }
- pos = help_pos(help_line_end+1);
- }
- }
-
- static void help_thumb_to_current_page()
- {
- int val = help_current_page*((long)HELP_SCROLL_MAX)/(help_length-help_prefix)+1;
- if (GetCtlValue(help_ctl) != val) SetCtlValue( help_ctl, val );
- }
-
- static void help_draw_current_page()
- {
- Rect r;
- GrafPtr save_port;
-
- GetPort( &save_port );
- SetPort( help_wind );
-
- help_thumb_to_current_page();
-
- r.top = HELP_MENU_H; r.left = 0; r.bottom = 32000; r.right = HELP_WIND_W-15;
- EraseRect( &r );
-
- help_draw_lines( 0, HELP_LINES );
-
- SetPort( save_port );
- }
-
- /*----------------------------------------------------------------------*/
-
- void help_show()
- {
- if (help_wind == NULL)
- SysBeep( 10 );
- else
- {
- SelectWindow( help_wind );
- ShowWindow( help_wind );
- }
- }
-
- void help_hide()
- {
- if (help_wind == NULL)
- SysBeep( 10 );
- else
- HideWindow( help_wind );
- }
-
- void help_hide_if_frontmost()
- {
- if ((help_wind != NULL) && (FrontWindow() == help_wind))
- HideWindow( help_wind );
- }
-
- void help_find( name )
- Str255 name;
- {
- int id, item, len;
- Str255 str;
- if (help_wind == NULL) return;
- if (name[0] > 0)
- {
- if ((name[0] == 1) && (name[1] == '-')) name[1] = 208; /* hack for - */
- id = HELP_INDEX_START;
- while (id < help_nb_menus)
- {
- item = help_menus_items[id+1]-help_menus_items[id];
- while (item > 0)
- {
- GetItem( help_menus[id], item, &str );
- len = str[0];
- if (len == name[0])
- {
- while (len>0) if (str[len] == name[len]) len--; else break;
- if (len == 0) goto found;
- }
- item--;
- }
- id++;
- }
- SysBeep(10);
- }
- id = 0;
- item = 1;
-
- found:
- help_current_page_set( help_items_val[help_menus_items[id]+item-1] );
- help_draw_current_page();
- if (!((WindowPeek)help_wind)->visible)
- {
- SelectWindow( help_wind );
- ShowWindow( help_wind );
- }
- }
-
- static void help_activate( activate )
- int activate;
- {
- if (help_wind != NULL)
- if (activate)
- ShowControl( help_ctl );
- else
- HideControl( help_ctl );
- }
-
- static void help_scroll_lines( n ) /* n = lines to scroll forward */
- int n;
- {
- if (n != 0)
- {
- long last_pos;
- int i = n;
- int j = 0;
- help_load_line( help_current_page+help_prefix );
- if (help_error) return;
- help_current_page_set( help_pos(help_line)-help_prefix );
- while (i != 0)
- {
- last_pos = help_current_page;
- if (i>0)
- {
- help_load_line( help_pos(help_line_end+1) );
- i--;
- }
- else
- {
- help_load_line( help_pos(help_line-1) );
- i++;
- }
- if (help_error) return;
- help_current_page_set( help_pos(help_line)-help_prefix );
- if (help_current_page == last_pos) break;
- j++;
- }
- if (j != 0)
- {
- Rect r;
- RgnHandle rgn;
- r.left = 0;
- r.right = HELP_WIND_W-15;
- r.top = HELP_MENU_H+HELP_TOP_SPACE;
- r.bottom = HELP_MENU_H+HELP_TOP_SPACE+HELP_LINE_H*HELP_LINES;
- rgn = NewRgn();
- if (n > 0)
- {
- ScrollRect( &r, 0, -HELP_LINE_H*j, rgn );
- help_draw_lines( HELP_LINES-j, HELP_LINES );
- }
- else
- {
- ScrollRect( &r, 0, HELP_LINE_H*j, rgn );
- help_draw_lines( 0, j );
- }
- DisposeRgn( rgn );
- if (help_error) return;
- help_thumb_to_current_page();
- }
- }
- }
-
- static pascal void help_scroll_proc( ctl, part )
- ControlHandle ctl;
- short part;
- {
- int n = 0;
- switch (part)
- {
- case inUpButton : n = -1; break;
- case inDownButton: n = 1; break;
- case inPageUp : n = -(HELP_LINES-2); break;
- case inPageDown : n = (HELP_LINES-2); break;
- }
- help_scroll_lines( n );
- }
-
- static void help_scroll( event, part )
- EventRecord *event;
- int part;
- {
- long oldval, newval;
- switch (part)
- {
- case inUpButton:
- case inDownButton:
- case inPageUp:
- case inPageDown:
- TrackControl( help_ctl, event->where, (ProcPtr)help_scroll_proc );
- break;
- case inThumb:
- oldval = GetCtlValue( help_ctl );
- TrackControl( help_ctl, event->where, 0L );
- newval = GetCtlValue( help_ctl );
- if ((newval != oldval) || (newval == 0) || (newval == HELP_SCROLL_MAX))
- {
- help_current_page_set( newval*(help_length-help_prefix)/((long)HELP_SCROLL_MAX) );
- help_draw_current_page();
- }
- break;
- default:
- SysBeep( 10 );
- break;
- }
- }
-
- static void help_menu_selection( event )
- EventRecord *event;
- {
- long selection = help_menu_select( event );
- if (selection != 0)
- {
- int id = selection>>16;
- int item = selection & 0xffff;
- if ((id >= HELP_MENUS_ID) && (id < HELP_MENUS_ID+help_nb_menus))
- {
- help_current_page_set( help_items_val[help_menus_items[id-HELP_MENUS_ID]+item-1] );
- help_draw_current_page();
- }
- }
- }
-
- static void help_update()
- {
- GrafPtr save_port;
- GetPort( &save_port );
- SetPort( help_wind );
- BeginUpdate( help_wind );
- DrawControls( help_wind );
- help_draw_menu_bar();
- help_draw_current_page();
- EndUpdate( help_wind );
- }
-
- int help_event( event )
- EventRecord *event;
- {
- WindowPtr w;
- ControlHandle ctl;
- GrafPtr save_port;
- int part;
-
- if (help_wind != NULL)
- switch (event->what)
- {
- case mouseDown:
- part = FindWindow( event->where, &w );
- if (w == help_wind)
- {
- switch (part)
- { case inGoAway:
- if (TrackGoAway( w, event->where )) help_hide();
- break;
- case inDrag:
- DragWindow( w, event->where, &screenBits.bounds );
- break;
- case inContent:
- if (w != FrontWindow())
- SelectWindow(w);
- else
- {
- GetPort( &save_port );
- SetPort( w );
- GlobalToLocal( &event->where );
- if (event->where.v < HELP_MENU_H)
- help_menu_selection( event );
- else
- {
- part = FindControl( event->where, w, &ctl );
- if (ctl == help_ctl) help_scroll( event, part );
- }
- SetPort( save_port );
- }
- break;
- }
- return 1;
- }
- break;
- case activateEvt:
- if ((WindowPtr)event->message == help_wind)
- { help_activate( event->modifiers & activeFlag ); return 1; }
- break;
- case updateEvt:
- if ((WindowPtr)event->message == help_wind)
- { help_update(); return 1; }
- break;
- }
-
- return 0;
- }
-
- /*----------------------------------------------------------------------*/
-